#include "../Map.h"
#include "../engines/SFMLMap.h"
#include "../engines/infoBox.h"
#include "../engines/grider.h"
#include "../extincludes/cpGUI.h"
#include <SFML/Graphics.hpp>

using namespace sf;

const int SCREEN_W = 400+MAP_DIM_MAX*TILE_DIM;
const int SCREEN_H = MAP_DIM_MAX*TILE_DIM+50;

Map mainTileset;
Map mainMap;
SFMLMap drawableMainMap;

RenderWindow App;
String mapTitle;

int create_map(string name, string width, string height);
int lload_map(string name);
grider grid(&App, SCREEN_W,SCREEN_H);

namespace new_map
{

   cp::cpGuiContainer myGUI;
   String Title;
   String error;
   vector<pair<String,cp::cpTextInputBox*> > iB;
   vector<string> champ;
   cp::cpButton* btn;
   cp::cpButton* btnOk;
   int ok;
   bool done;
   
   const int NONE = 0;
   const int NP = 1;
   const int ERROR = 2;
   
   void init()
   {
      Title = String("Nouvelle map (../datas/maps)", sf::Font::GetDefaultFont(), 30);
      Title.SetColor(Color::White);
      Title.SetPosition(850-Title.GetRect().GetWidth(),250);
      
      string name[3] = {"Nom de la map : ", "Largeur (1-20): ", "Hauteur (1-20): "};
      
      for(int i = 0 ; i < 3 ; i++)
      {
         String b = String(name[i], sf::Font::GetDefaultFont(), 20);
         b.SetColor(Color::White);
         b.SetPosition(600-b.GetRect().GetWidth(),300+30*i);
         cp::cpTextInputBox *a = new cp::cpTextInputBox(&App, &myGUI, "", 600, 300+30*i, 230, 20);
         iB.push_back(make_pair(b,a));
         champ.push_back("");
      }
      
      btn = new cp::cpButton(&App, &myGUI, "Creer", 600, 440, 70, 30);
      btnOk = new cp::cpButton(&App, &myGUI, "Ok", 600, 440, 70, 30);
      btnOk->Show(false);
   }
   
   void re_init()
   {
      ok = NONE;
      btn->Show(true);
      btnOk->Show(false);
      for(int i = 0 ; i < iB.size() ; i++)
         iB[i].second->Show(true);
   }

   void handle_event(Event event)
   {
      for(int i = 0 ; i < iB.size() ; i++)
         iB[i].second->ProcessTextInput(&event);
      myGUI.ProcessKeys(&event);
   }

   void handle_action(const Input& input)
   {
      for(int i = 0 ; i < iB.size() ; i++)
         if(iB[i].second->CheckState(&input) == cp::CP_ST_NONE)
         {
            string a = iB[i].second->GetLabelText();
            if(a != "")
               champ[i] = a;
              
         }
      
      if(btn->CheckState(&input) == cp::CP_ST_MOUSE_LBUTTON_RELEASED)
			ok = create_map(champ[0],champ[1],champ[2]);
      if(btnOk->CheckState(&input) == cp::CP_ST_MOUSE_LBUTTON_RELEASED)
      {
         done = true;
         re_init();
      }
   }

   void draw()
   {
      App.Draw(Title);
      
      if(ok != NONE)
      {
         App.Draw(error);
         btn->Show(false);
         btnOk->Show(true);
         for(int i = 0 ; i < iB.size() ; i++)
            iB[i].second->Show(false);
      }
         
      for(int i = 0 ; i < iB.size() ; i++)
      {
         if(ok == NONE)
            App.Draw(iB[i].first);
         iB[i].second->Draw();
      }
      
      btn->Draw();
      btnOk->Draw();
   }
   
   void uninit()
   {
      iB.clear();
      delete btn;
   }
}

namespace load_map
{

   cp::cpGuiContainer myGUI;
   String Title;
   String error;
   vector<pair<String,cp::cpTextInputBox*> > iB;
   vector<string> champ;
   cp::cpButton* btn;
   cp::cpButton* btnOk;
   int ok;
   bool done;
   
   const int NONE = 0;
   const int NP = 1;
   const int ERROR = 2;
   
   void init()
   {
      Title = String("Charger une map (../datas/maps)", sf::Font::GetDefaultFont(), 30);
      Title.SetColor(Color::White);
      Title.SetPosition(850-Title.GetRect().GetWidth(),250);
      
      string name[1] = {"Nom de la map : "};
      
      for(int i = 0 ; i < 1 ; i++)
      {
         String b = String(name[i], sf::Font::GetDefaultFont(), 20);
         b.SetColor(Color::White);
         b.SetPosition(600-b.GetRect().GetWidth(),300+30*i);
         cp::cpTextInputBox *a = new cp::cpTextInputBox(&App, &myGUI, "", 600, 300+30*i, 230, 20);
         iB.push_back(make_pair(b,a));
         champ.push_back("");
      }
      
      btn = new cp::cpButton(&App, &myGUI, "Charger", 600, 440, 70, 30);
      btnOk = new cp::cpButton(&App, &myGUI, "Ok", 600, 440, 70, 30);
      btnOk->Show(false);
   }
   
   void re_init()
   {
      ok = NONE;
      btn->Show(true);
      btnOk->Show(false);
      for(int i = 0 ; i < iB.size() ; i++)
         iB[i].second->Show(true);
   }

   void handle_event(Event event)
   {
      for(int i = 0 ; i < iB.size() ; i++)
         iB[i].second->ProcessTextInput(&event);
      myGUI.ProcessKeys(&event);
   }

   void handle_action(const Input& input)
   {
      for(int i = 0 ; i < iB.size() ; i++)
         if(iB[i].second->CheckState(&input) == cp::CP_ST_NONE)
         {
            string a = iB[i].second->GetLabelText();
            if(a != "")
               champ[i] = a;
         }
      
      if(btn->CheckState(&input) == cp::CP_ST_MOUSE_LBUTTON_RELEASED)
			ok = lload_map(champ[0]);
      if(btnOk->CheckState(&input) == cp::CP_ST_MOUSE_LBUTTON_RELEASED)
      {
         done = true;
         re_init();
      }
   }

   void draw()
   {
      App.Draw(Title);
      
      if(ok != NONE)
      {
         App.Draw(error);
         btn->Show(false);
         btnOk->Show(true);
         for(int i = 0 ; i < iB.size() ; i++)
            iB[i].second->Show(false);
      }
         
      for(int i = 0 ; i < iB.size() ; i++)
      {
         if(ok == NONE)
            App.Draw(iB[i].first);
         iB[i].second->Draw();
      }
      
      btn->Draw();
      btnOk->Draw();
   }
   
   void uninit()
   {
      iB.clear();
      delete btn;
   }
}


int lload_map(string name)
{
   if(name == "")
   {
      load_map::error = String("Il faut remplir le champ !",Font::GetDefaultFont(),25);
      load_map::error.SetPosition(load_map::Title.GetPosition().x,load_map::Title.GetPosition().y+50);
      load_map::error.SetColor(Color::Red);
      return load_map::ERROR;
   }
   
   if(!mainMap.load(string(map_path+name).c_str()))
   {
      load_map::error = String("Cette map n'existe pas !",Font::GetDefaultFont(),25);
      load_map::error.SetPosition(load_map::Title.GetPosition().x,load_map::Title.GetPosition().y+50);
      load_map::error.SetColor(Color::Red);
      return load_map::ERROR;
   }
   mapTitle.SetText(name);
   mapTitle.SetFont(Font::GetDefaultFont());
   mapTitle.SetColor(Color::Red);
   mapTitle.SetSize(25);
   mapTitle.SetPosition((SCREEN_W+mapTitle.GetRect().GetWidth())/2, 5);
   
   load_map::error = String("Rock'n'roll !",Font::GetDefaultFont(),25);
   load_map::error.SetPosition(load_map::Title.GetPosition().x,load_map::Title.GetPosition().y+50);
   load_map::error.SetColor(Color::Green);
   grid.genGrid(pix_coord(mainTileset.mapPixDim.width+20,15+mapTitle.GetRect().GetHeight()), mainMap.mapDim.width, mainMap.mapDim.height, 3, Color::White);

   mainMap.calc_coord_on_screen(grid.left_top);
   
   drawableMainMap = SFMLMap(&App,&mainMap);
   drawableMainMap.initSelector(Color::Red);
   
   return load_map::NP;
}


int create_map(string name, string width, string height)
{
   if(name == "" || width == "" || height == "")
   {
      new_map::error = String("Il faut remplir tous les champs !",Font::GetDefaultFont(),25);
      new_map::error.SetPosition(new_map::Title.GetPosition().x,new_map::Title.GetPosition().y+50);
      new_map::error.SetColor(Color::Red);
      return new_map::ERROR;
   }
   
   map_dim dim(string_to_int(height),string_to_int(width));
   
   if(dim.width > 0 && dim.width <= MAP_DIM_MAX && dim.height > 0 && dim.height <= MAP_DIM_MAX)
   {
      mainMap.mapDim = dim;
      mainMap.save(string(map_path+name).c_str());
      mainMap.setSpace(3,3);
      
      mapTitle.SetText(name);
      mapTitle.SetFont(Font::GetDefaultFont());
      mapTitle.SetColor(Color::Red);
      mapTitle.SetSize(25);
      mapTitle.SetPosition((SCREEN_W+mapTitle.GetRect().GetWidth())/2, 5);
      
      new_map::error = String("Rock'n'roll !",Font::GetDefaultFont(),25);
      new_map::error.SetPosition(new_map::Title.GetPosition().x,new_map::Title.GetPosition().y+50);
      new_map::error.SetColor(Color::Green);
      grid.genGrid(pix_coord(mainTileset.mapPixDim.width+20,15+mapTitle.GetRect().GetHeight()), mainMap.mapDim.width, mainMap.mapDim.height, 3, Color::White);
      
      mainMap.start = pix_coord(grid.left_top);
      mainMap.calc_coord_on_screen();
      drawableMainMap = SFMLMap(&App,&mainMap);
      drawableMainMap.initSelector(Color::Red);
      
      return new_map::NP;
   }
   else
   {
      new_map::error = String("Dimensions invalides !",Font::GetDefaultFont(),25);
      new_map::error.SetPosition(new_map::Title.GetPosition().x,new_map::Title.GetPosition().y+50);
      new_map::error.SetColor(Color::Red);
      return new_map::ERROR;
   }
}

int main()
{      
   App.Create(VideoMode(SCREEN_W,SCREEN_H), "Tower Defense - map editor");

   SFMLMap::loadTilesetImage();
   
   mainTileset.load(string(tileset_def_path+string("test.tsdef")).c_str());
   mainTileset.setSpace(5,5);
   mainTileset.calc_coord_on_screen();
   
   SFMLMap drawableMainTileset(&App,&mainTileset);
   drawableMainTileset.initSelector(Color::Blue);
   
   grid.addSeparator(mainTileset.mapPixDim.width+5, grider::Vertical, 5, Color::Blue);

   infoBox titre(&App,pix_coord(0,mainTileset.mapPixDim.height+5), pix_coord(mainTileset.mapPixDim.width+5,mainTileset.mapPixDim.height+5), "../datas/fonts/Futured.TTF");
      titre.addItem("Commandes",30,infoBox::Center);
   
   infoBox legende_commandes(&App,pix_coord(0,titre.upLeft.y+titre.boxDim.height+20), 
                             pix_coord(mainTileset.mapPixDim.width+5, titre.upLeft.y+titre.boxDim.height), "../datas/fonts/Futured.TTF");
      legende_commandes.addItem("Nouvelle map : N\n",25,infoBox::Left,Color::Green,30);
      legende_commandes.addItem("Charger map : C\n",25,infoBox::Left,Color::Green,30);
      legende_commandes.addItem("Enregistrer map : S\n",25,infoBox::Left,Color::Green,30);
      //legende_commandes.addItem("Enregistrer map sous : CTRL+S\n",20,infoBox::Left,Color::Green,30);

   bool show_grid = true;

   bool show_new_map = false;
   bool show_load_map = false;
 
   new_map::init();
 
   load_map::init();

   const Input& input = App.GetInput();
   
   bool show_saved = false;
   
   String Saved;
   Saved.SetText("Map saved !");
   Saved.SetColor(Color::Green);
   Saved.SetFont(Font::GetDefaultFont());
   Saved.SetSize(25);
   Saved.SetPosition(SCREEN_W-Saved.GetRect().GetWidth(),Saved.GetRect().GetHeight()/2-10);
   
   Clock c;
   
   while(App.IsOpened())
   {
      Event event;
      while(App.GetEvent(event))
      {
         switch(event.Type)
         {
            case Event::Closed:
               App.Close();
               break;
               
            case Event::KeyPressed:
               switch(event.Key.Code)
               {
                  case Key::Right:
                     drawableMainTileset.moveSelector(RIGHT);
                     drawableMainMap.moveSelector(RIGHT);
                     break;
                  case Key::Left:
                     drawableMainTileset.moveSelector(LEFT);
                     drawableMainMap.moveSelector(LEFT);
                     break;
                  case Key::Up:
                     drawableMainTileset.moveSelector(UP);
                     drawableMainMap.moveSelector(UP);
                     break;
                  case Key::Down:
                     drawableMainTileset.moveSelector(DOWN);
                     drawableMainMap.moveSelector(DOWN);
                     break;
                     
                  case Key::Return:
                     if(!show_load_map && ! show_new_map)
                     {
                        if(!drawableMainMap.isActive())
                        {
                           drawableMainMap.activeSelector();
                           drawableMainMap.showSelector();
                           map_coord posOnTileset = drawableMainTileset.posSelector;
                           drawableMainMap.setSpriteOnSelector(drawableMainTileset.sprite_on_layer[L_SOL][posOnTileset.iLig][posOnTileset.iCol]);
                           drawableMainTileset.unactiveSelector();
                        }
                        else
                        {
                           mainMap.setValue(L_SOL,drawableMainMap.posSelector) = mainTileset.getValue(L_SOL,drawableMainTileset.posSelector);
                           drawableMainMap.setSprite(L_SOL,drawableMainMap.posSelector,  drawableMainTileset.getSprite(L_SOL,drawableMainTileset.posSelector));
                        }
                        
                     }
                     break;
                     
                  case Key::Tab:
                     if(drawableMainMap.isActive())
                     {
                        drawableMainMap.unactiveSelector();
                        drawableMainMap.unshowSelector();
                        drawableMainTileset.activeSelector();
                     }
                     break;
                     
                  case Key::Escape:
                     if(show_new_map)
                     {
                        show_new_map = false;
                        new_map::done = true;
                        new_map::re_init();
                     }
                     else
                        App.Close();
                     break;
                     
                  case Key::N:
                     if(!show_load_map)
                     {
                        show_new_map = true;
                        new_map::done = false; 
                     }
                     break;
                  
                  case Key::S:
                     if(!mainMap.isLoaded() && !show_load_map)
                     {
                        show_new_map = true;
                        new_map::done = false; 
                     }
                     else
                     {
                        if(!show_load_map && !show_new_map)
                        {
                           show_saved = true;
                           mainMap.save();
                           c.Reset();
                        }
                     }
                     break;
                     
                  case Key::C:
                     if(!show_new_map)
                     {
                        show_load_map = true;
                        load_map::done = false; 
                     }
                     break;
                
                  case Key::G:
                     show_grid = !show_grid;
                     break;
                  
               }
               break;
         }
         
         if(show_new_map)
            new_map::handle_event(event);
         if(show_load_map)
            load_map::handle_event(event);
      }
      
      if(show_new_map)
         new_map::handle_action(input);
      if(show_load_map)
         load_map::handle_action(input);
         
      if(show_new_map)
         show_new_map = !new_map::done;
      if(show_load_map)
         show_load_map = !load_map::done;  
      
      App.Clear(); 
      
      titre.draw();
      legende_commandes.draw();  
      
      if(show_saved)
      {
         Saved.SetColor(Color(0,255,0,255*(1-c.GetElapsedTime())));
         App.Draw(Saved);
      }
      
      if(c.GetElapsedTime() >= 0.9f)
         show_saved = false;
      
      if(!show_new_map && !show_load_map)
      {
         if(show_grid)
            grid.draw();
         App.Draw(mapTitle);
      }
      
      if(show_new_map)
      {
         new_map::draw();
         drawableMainTileset.unactiveSelector();
         drawableMainTileset.unshowSelector();
      }
      if(show_load_map)
      {
         load_map::draw();
         drawableMainTileset.unactiveSelector();
         drawableMainTileset.unshowSelector();
      }
   
      if(mainMap.isLoaded() && !show_load_map && !show_new_map)
      {
         drawableMainTileset.showSelector();
         if(!drawableMainMap.isActive())
            drawableMainTileset.activeSelector();
         drawableMainMap.draw();
      }
      
      drawableMainTileset.draw();
      
      App.Display();
   }
   
   new_map::uninit();
   load_map::uninit();
}

